package com.mpgame.handler;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.mpgame.caller.*;
import com.mpgame.common.connection.DynamicGrpcPoolProvider;
import com.mpgame.common.connection.GrpcConnectionPool;
import com.mpgame.common.handler.BaseHandler;
import com.mpgame.common.proto.*;
import com.mpgame.common.utils.ConsulServiceDiscovery;
import com.mpgame.common.utils.Log;
import com.mpgame.connection.ChannelRegistry;

import io.netty.channel.ChannelHandlerContext;

public class ForwardHandler extends BaseHandler {

    private GrpcConnectionPool socialPool, gamePool, battlePool;
    private ChatServiceCaller chatCaller;
    private GameServiceCaller gameCaller;
    private BattleServiceCaller battleCaller;

    private final ConsulServiceDiscovery discovery;
    private final DynamicGrpcPoolProvider poolProvider;

    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public ForwardHandler() {
        super("ForwardHandler", 100, true);

        String consulHost = System.getProperty("consul.host", System.getenv().getOrDefault("CONSUL_HOST", "localhost"));
        int consulPort = Integer.getInteger("consul.port",
                Integer.parseInt(System.getenv().getOrDefault("CONSUL_PORT", "8500")));
        this.discovery = new ConsulServiceDiscovery(consulHost, consulPort);
        this.poolProvider = new DynamicGrpcPoolProvider(discovery);
        Log.info("ForwardHandler 初始化完成，等待服务发现...");
        startHealthLoop();
    }

    @Override
    public boolean handle(ChannelHandlerContext ctx, GamePacket pkt) {
        try {
            if (!ChannelRegistry.getAuthenticated(ctx.channel())) {
                Log.warn("收到新连接客户端的请求，但该连接未验证，拒绝处理");
                sendErr(ctx, "未通过Token验证！");
                return false;
            }
            switch (pkt.getCmd()) {
                case CHAT_REQ:
                    if (chatCaller == null)
                        return serviceNotReady(ctx, "social-service");
                    return chatCaller.handleChat(ctx, pkt);
                case GAME_INITDATA_REQ:
                    if (gameCaller == null)
                        return serviceNotReady(ctx, "game-service");
                    return gameCaller.handleGameInitData(ctx, pkt);
                case GAME_MOVE_TO_REQ:
                    if (gameCaller == null)
                        return serviceNotReady(ctx, "game-service");
                    return gameCaller.handleGameMoveTo(ctx, pkt);
                case GAME_CHAT_REQ:
                    if (gameCaller == null)
                        return serviceNotReady(ctx, "game-service");
                    return gameCaller.handleGameChat(ctx, pkt);
                case GAME_SWITCH_SCENE_REQ:
                    if (gameCaller == null)
                        return serviceNotReady(ctx, "game-service");
                    return gameCaller.handleGameSwitchScene(ctx, pkt);
                case BATTLE_INVITE_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleInvite(ctx, pkt);
                case BATTLE_INVITE_REFUSE_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleInviteRefuse(ctx, pkt);
                case BATTLE_START_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleStart(ctx, pkt);
                case BATTLE_MATCH_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleMatch(ctx, pkt);
                case BATTLE_ACTION_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleAction(ctx, pkt);
                case BATTLE_ANIMATION_FINISHED_PLAY_REQ:
                    if (battleCaller == null)
                        return serviceNotReady(ctx, "battle-service");
                    return battleCaller.handleBattleAnimationFinishedPlay(ctx, pkt);

                default:
                    Log.warn("未知的命令类型，无法转发：" + pkt.getCmd());
                    return false;
            }
        } catch (Exception e) {
            Log.err("转发处理器处理异常：" + e.getMessage());
            return false;
        }
    }

    private void sendErr(ChannelHandlerContext ctx, String errMsg) {
        ctx.writeAndFlush(GamePacket.newBuilder()
                .setCmd(CmdId.GAME_AUTH_RSP)
                .setEc(ErrorCode.AUTH_REQUIRED)
                .setData(ErrMsg.newBuilder().setErrMsg("未通过Token验证！").build().toByteString())
                .build());
    }
    private boolean serviceNotReady(ChannelHandlerContext ctx, String svc) {
        Log.warn("请求被拒绝，目标服务未就绪: " + svc);
        sendErr(ctx, "服务暂不可用");
        return false;
    }

    private void startHealthLoop() {
        scheduler.scheduleAtFixedRate(this::checkPools, 3, 5, TimeUnit.SECONDS);
    }

    private void checkPools() {
        try {
            // social-service
            if (socialPool == null || !socialPool.isHealthy()) {
                rebuild("social-service", 3, 15);
            }
            // game-service
            if (gamePool == null || !gamePool.isHealthy()) {
                rebuild("game-service", 5, 20);
            }
            // battle-service
            if (battlePool == null || !battlePool.isHealthy()) {
                rebuild("battle-service", 5, 20);
            }
        } catch (Exception e) {
            Log.err("连接池健康检查异常: " + e.getMessage());
        }
    }

    private void rebuild(String svc, int core, int max) {
        GrpcConnectionPool newPool = poolProvider.getPool(svc, core, max);
        if (newPool == null) {
            Log.warn("未找到可用实例，跳过重建: " + svc);
            removeCaller(svc);
            return;
        }
        switch (svc) {
            case "social-service":
                socialPool = newPool;
                chatCaller = new ChatServiceCaller(socialPool);
                break;
            case "game-service":
                gamePool = newPool;
                gameCaller = new GameServiceCaller(gamePool);
                break;
            case "battle-service":
                battlePool = newPool;
                battleCaller = new BattleServiceCaller(battlePool);
                break;
        }
        Log.info("重建连接池并更新 Caller: " + svc);
    }

    private void removeCaller(String svc) {
        switch (svc) {
            case "social-service":
                chatCaller = null;
                socialPool = null;
                break;
            case "game-service":
                gameCaller = null;
                gamePool = null;
                break;
            case "battle-service":
                battleCaller = null;
                battlePool = null;
                break;
        }
    }
}
